﻿using IMDb_Scraper;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Windows.Forms;
using System.Xml.Serialization;

namespace MovieViewerLib
{
    public class ImdbHelper
    {
        public static MovieCollection movies = null;
        public MovieListView imageListView1 = null;
        string thumbnailPath = null;
        string cacheFilePath = null;
        public ImdbHelper(MovieListView imageListView)
        {
            imageListView1 = imageListView;
            string appRoot = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
            thumbnailPath = string.Format(@"{0}\Thumbnails", appRoot);
            cacheFilePath = string.Format(@"{0}\Movies.xml", appRoot);
            if (!Directory.Exists(thumbnailPath))
                Directory.CreateDirectory(thumbnailPath);
        }
        public string GetMovie(MovieListViewItem item, string file, string matchingMovieName)
        {
            Interlocked.Increment(ref Utility.counter);
            var mm = (item != null)?
                movies.Movie.Where(m => m.LocalName.ToLower() == item.MatchingName.ToLower()).FirstOrDefault() :
                movies.Movie.Where(m => (!string.IsNullOrEmpty(m.LocalName) ? m.LocalName.ToLower() : m.Name.ToLower()) == matchingMovieName.ToLower()).FirstOrDefault();
            if (mm == null)
            {
                mm = new Movie();
                movies.Movie.Add(mm);
                PopulateItem(item, file, matchingMovieName, mm);
                Interlocked.Increment(ref Utility.NotFoundCounter);
            }
            else if (item != null)
            {
                PopulateItem(item, file, matchingMovieName, mm);
                Utility.Log("Not Processed: " + file);
            }
            else if (mm != null)
                Interlocked.Increment(ref Utility.foundCounter);
            else
                Utility.Log("Not Processed: " + file);

            if (item == null)
            {
                string imageFile = null;
                if (!string.IsNullOrWhiteSpace(mm.ImageThumbnail))
                    imageFile = LoadImage(mm);
                imageListView1.Items.Add(imageFile, file, matchingMovieName, mm.Name, mm.Rating, mm.Genre, mm.Year, mm.Id, TimeSpan.FromMinutes(mm.Duration));
                imageListView1.AllItems.Add(imageFile, file, matchingMovieName, mm.Name, mm.Rating, mm.Genre, mm.Year, mm.Id, TimeSpan.FromMinutes(mm.Duration));
            }
            else
                Utility.Log("Not Processed: " + file);
            return mm.LocalImageThumbnail;
        }

        private void PopulateItem(MovieListViewItem item, string file, string matchingMovieName, Movie mm)
        {
            mm.LocalName = item != null ? item.MatchingName : matchingMovieName;
            UpdateMovie(file, matchingMovieName, mm);
            if (item != null)
            {
                item.MovieName = mm.Name;
                item.Rating = mm.Rating;
                item.Genre = mm.Genre;
                item.Year = mm.Year;
                item.Duration = TimeSpan.FromMinutes(mm.Duration);
                item.Id = mm.Id;
                LoadImage(mm);
            }
        }

        //public string GetMovie(string file, string matchingMovieName)
        //{ 
        
        //}

        public void UpdateCache()
        {
            lock (syncObj)
            {
                using (var fs = new FileStream(cacheFilePath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
                {
                    new XmlSerializer(typeof(MovieCollection)).Serialize(fs, movies);
                }
            }
            //new JsonSerializer().Serialize()
        }
        static object syncObj = new object();
        public void UpdateMovie(string file, string matchingMovieName, Movie mm)
        {
            IMDb imdb = GetImdbMovie(matchingMovieName);
            if (imdb != null && imdb.Id != null)
            {
                mm.Name = HttpUtility.HtmlDecode(string.IsNullOrWhiteSpace(imdb.OriginalTitle) ? imdb.Title : imdb.OriginalTitle);
                //mm.LocalName = matchingMovieName;
                mm.Rating = imdb.Rating;
                //mm.Genre = imdb.Genres.Count > 0 ? string.Format("{0}, {1}", imdb.Genres[0], imdb.Genres[1])  : string.Empty;
                mm.Genre = imdb.Genres.Count > 0 ? (string.Format("{0}", imdb.Genres.Count > 1 ? 
                    string.Format("{0}, {1}", imdb.Genres[0], imdb.Genres[1]) : imdb.Genres[0])) : string.Empty;
                mm.ImageThumbnail = imdb.Poster;                
                mm.Year = imdb.Year;
                mm.Duration = string.IsNullOrEmpty(imdb.Runtime) ? 0 : int.Parse(imdb.Runtime);
                if (mm.Id != imdb.Id)
                    mm.LocalImageThumbnail = null;
                mm.Id = imdb.Id;
            }
            else
            {
                mm.Name = matchingMovieName;
                mm.LocalName = matchingMovieName;
            }
            //mm.Size = Math.Ceiling((double)new FileInfo(file).Length / (1024 * 1024)).ToString();
            mm.FullLocalPath = file;
        }

        private string LoadImage(Movie mm)
        {
            string imagePath = string.Format(@"{0}\{1}.jpg", thumbnailPath, mm.Id.ToString());
            if (File.Exists(imagePath))
            {
                //Interlocked.Increment(ref Utility.foundCounter);
                //Utility.Log("Found: " + mm.Name);
                return mm.LocalImageThumbnail = imagePath;
            }
            //Interlocked.Increment(ref Utility.NotFoundCounter);
            string url = string.IsNullOrWhiteSpace(mm.LocalImageThumbnail) ? mm.ImageThumbnail : mm.LocalImageThumbnail;
            if (string.IsNullOrEmpty(url))
                return null;
            System.Net.WebRequest request = System.Net.WebRequest.Create(url);
            System.Net.WebResponse response = null;
            try
            {
                response = request.GetResponse();
            }
            catch (Exception ex)
            {
                using (var sw = new StreamWriter(new FileStream("ErrorLog.txt", FileMode.Append, FileAccess.Write, FileShare.ReadWrite)))
                {
                    sw.WriteLineAsync(string.Format("Error while loading image for file: {0}. {1}", mm.FullLocalPath, ex.Message));
                }
            }
            System.IO.Stream responseStream =
                response.GetResponseStream();

            Bitmap bmp = new Bitmap(responseStream);
            if (string.IsNullOrWhiteSpace(mm.LocalImageThumbnail))
            {
                bmp.Save(imagePath);
                mm.LocalImageThumbnail = imagePath;
            }
            responseStream.Dispose();
            return mm.LocalImageThumbnail;
        }

        private IMDb GetImdbMovie(string matchingMovieName)
        {
            IMDb imdb = null;
            for (int i = 0; i < 3; i++)
            {
                try
                {
                    imdb = new IMDb(matchingMovieName);
                    break;
                }
                catch (WebException ex)
                {
                    if (i == 2)
                        using (var sw = new StreamWriter(new FileStream("ErrorLog.txt", FileMode.Append, FileAccess.Write, FileShare.ReadWrite)))
                        {
                            sw.WriteLineAsync(string.Format("Error while getting imdb data for file: {0}. {1}", matchingMovieName, ex.Message));
                        }
                }
            }
            return imdb;
        }
    }
}
